-
Notifications
You must be signed in to change notification settings - Fork 15.2k
Add isTrivial() and isTriviallyCopyable() AST matchers #90634
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-clang Author: None (higher-performance) ChangesThere are currently no AST matchers for the equivalent of This pull request adds matchers to check if records and their member functions are trivial. It does not attempt to handle other trivial entities (such as pointers). Full diff: https://github.com/llvm/llvm-project/pull/90634.diff 2 Files Affected:
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 2f71053d030f68..f8529105f8d034 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -5440,6 +5440,43 @@ AST_MATCHER(FunctionDecl, isDefaulted) {
return Node.isDefaulted();
}
+/// Matches trivial methods and types.
+///
+/// Given:
+/// \code
+/// class A { A(); };
+/// A::A() = default;
+/// class B { B() = default; };
+/// \endcode
+/// cxxMethodDecl(isTrivial())
+/// matches the declaration of B, but not A.
+AST_POLYMORPHIC_MATCHER(isTrivial,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(CXXMethodDecl,
+ CXXRecordDecl)) {
+ if (const auto *E = dyn_cast<CXXMethodDecl>(&Node))
+ return E->isTrivial();
+ if (const auto *E = dyn_cast<CXXRecordDecl>(&Node)) {
+ const auto *Def = Node.getDefinition();
+ return Def && Def->isTrivial();
+ }
+ return false;
+}
+
+/// Matches trivially copyable types.
+///
+/// Given:
+/// \code
+/// class A { A(const A &); };
+/// A::A(const A &) = default;
+/// class B { B(const B &) = default; };
+/// \endcode
+/// cxxMethodDecl(isTriviallyCopyable())
+/// matches the declaration of B, but not A.
+AST_MATCHER(CXXRecordDecl, isTriviallyCopyable) {
+ CXXRecordDecl *Def = Node.getDefinition();
+ return Def && Def->isTriviallyCopyable();
+}
+
/// Matches weak function declarations.
///
/// Given:
diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index 87774b00956a5a..9c648588ba970c 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -1849,6 +1849,33 @@ TEST_P(ASTMatchersTest, IsDeleted) {
functionDecl(hasName("Func"), isDeleted())));
}
+TEST_P(ASTMatchersTest, IsTrivial) {
+ if (!GetParam().isCXX()) {
+ return;
+ }
+
+ EXPECT_TRUE(notMatches("class A { A(); };",
+ cxxRecordDecl(hasName("A"), isTrivial())));
+ EXPECT_TRUE(matches("class B { B() = default; };",
+ cxxRecordDecl(hasName("B"), isTrivial())));
+
+ EXPECT_TRUE(notMatches("class A { ~A(); }; A::~A() = default;",
+ cxxMethodDecl(hasName("~A"), isTrivial())));
+ EXPECT_TRUE(matches("class B { ~B() = default; };",
+ cxxMethodDecl(hasName("~B"), isTrivial())));
+}
+
+TEST_P(ASTMatchersTest, IsTriviallyCopyable) {
+ if (!GetParam().isCXX()) {
+ return;
+ }
+
+ EXPECT_TRUE(notMatches("class A { ~A(); }; A::~A() = default;",
+ cxxRecordDecl(hasName("A"), isTriviallyCopyable())));
+ EXPECT_TRUE(matches("class B { ~B() = default; };",
+ cxxRecordDecl(hasName("B"), isTriviallyCopyable())));
+}
+
TEST_P(ASTMatchersTest, IsNoThrow_DynamicExceptionSpec) {
if (!GetParam().supportsCXXDynamicExceptionSpecification()) {
return;
|
|
|
125ec4e to
013b692
Compare
a58dbe9 to
f981f44
Compare
|
I remember back in the day that adding new matchers was a problem because it grew the size of the files beyond some supported compiler's limit. Could @AaronBallman or someone else knowledgable about this(cc @kadircet) take a look and confirm adding matchers is fine now? |
| return Node.isDefaulted(); | ||
| } | ||
|
|
||
| /// Matches trivial methods and types. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not think is actually matches types, but rather classes or CXXRecordDecl.
And the question is: should it?
I believe we could extend this matcher to also work on types and type locs.
Do you see any downsides to that? (same for the other matcher)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I see, yeah. I don't think we want to support that since the other matchers don't do that either (e.g., isSameOrDerivedFrom). That seems like a higher-level design change that should be made uniformly if it's desired.
We generally only add matchers when there's a need for them to reside in-tree (e.g., a few clang-tidy checks will use them); otherwise we recommend that folks define their own custom matchers. The reason is mostly because compile time overhead for compiling ASTMatchers.h is... huge... due to the template instantiations, so we usually want there to be a need before adding any. Is there a planned need here? |
|
@AaronBallman: Oh I see. I didn't have any plans to upstream any matchers that used this, though I suppose I could. The check I had in mind though ostensibly could be in-tree, if you guys were interested. Though now that I think about it more, I think it would need which is frequently (but not always) dubious. which results in a dangling pointer. |
|
Thanks for the details! I'd say let's hold off on adding these matchers; if you have a check that needs them, then you could look through clang-tidy to see if other checks have also added a local matcher for the same thing, and if there's two or more matchers needing it, then we'll add it as a global matcher. As for the check itself, that looks like an interesting one! |
|
@AaronBallman that makes sense, thanks! For
Is that worth adding/migrating to? Otherwise, for |
|
While the libc++ checks are in the same tree as clang-tidy itself we (libc++) don't actually consider them in-tree, since they are compiled as a plugin against a clang-tidy that's already installed on the system. |
|
Thanks! I'll close this for now then. |
There are currently no AST matchers for the equivalent of
std::is_trivial,std::is_trivially_default_constructible,std::is_trivially_copyable, and the like.This pull request adds matchers to check if records and their member functions are trivial.
It does not attempt to handle other trivial entities (such as pointers).